﻿/*
 * modbusrtumaster.cpp
 *
 *  Created on: 2017年3月14日
 *      Author: work
 */

#include <dm/export.hpp>

#define DM_API_PROTOCOL DM_API_EXPORT

#include <dm/protocol/modbusrtumaster.hpp>
#include <dm/os/log/logger.hpp>

namespace dm{
namespace protocol{

static const char* logModule = "CModbusRtuMaster.protocol.dm";

CModbusRtuMaster::CModbusRtuMaster():CProtocol(),CModbusRtu(){
	setWaitTimeout(5);
	setWaitMaxTimes(3);
	log().debug(THISMODULE "创建对象,默认等待响应时间%d,重试次数%d",m_waitTimeout,m_timeoutMaxTimes);
}

CModbusRtuMaster::~CModbusRtuMaster(){
	log().debug(THISMODULE "销毁对象");
}

/**
 * 处理接收到的帧
 * @param now
 * @return
 */
CModbusRtuMaster::EAction CModbusRtuMaster::dealRxFrame( const ts_t& ts,const rts_t& rts ){
	if( rxFrame().getFunc()!=txFrame().getFunc() ){
		log().debug(THISMODULE "接收到的功能码%02X与发送%02X不一致",rxFrame().getFunc(),txFrame().getFunc());
		return Action_Nothing;
	}

	// 收发进行对比，接收到的应该和发送的相对应
	switch( rxFrame().getFunc() ){
	case CFrameModbusRtu::ReadCoilStatus:
		log().debug(THISMODULE "ReadCoilStatus");
		return dealRxResponse_readCoils( rxFrame(),txFrame(),ts,rts );

	case CFrameModbusRtu::ReadInputStatus:
		log().debug(THISMODULE "ReadInputStatus");
		return dealRxResponse_readDiscreteInputs( rxFrame(),txFrame(),ts,rts );

	case CFrameModbusRtu::ReadHoldReg:
		log().debug(THISMODULE "ReadHoldReg");
		return dealRxResponse_readHoldingRegisters(rxFrame(),txFrame(),ts,rts );

	case CFrameModbusRtu::ReadInputReg:
		log().debug(THISMODULE "ReadInputReg");
		return dealRxResponse_readInputRegisters(rxFrame(),txFrame(),ts,rts );

	case CFrameModbusRtu::ForceSigCoil:
		log().debug(THISMODULE "ForceSigCoil");
		return dealRxResponse_writeSingleCoil(rxFrame(),txFrame(),ts,rts );

	case CFrameModbusRtu::PresetSigReg:
		log().debug(THISMODULE "PresetSigReg");
		return dealRxResponse_writeSingleRegister(rxFrame(),txFrame(),ts,rts );

	case CFrameModbusRtu::ForceMtlCoil:
		log().debug(THISMODULE "ForceMtlCoil");
		return dealRxResponse_writeMultipleCoils( rxFrame(),txFrame(),ts,rts );

	case CFrameModbusRtu::PresetMtlReg:
		log().debug(THISMODULE "PresetMtlReg");
		return dealRxResponse_writeMultipleRegisters( rxFrame(),txFrame(),ts,rts );

	default:
		log().debug(THISMODULE "未支持功能码%02X",rxFrame().getFunc());
		return Action_Nothing;
	}
}

CFrameModbusRtu* CModbusRtuMaster::genRxTempFrame(){
	log().debug(THISMODULE "设置上行报文");
	CFrameModbusRtu* f = new CFrameModbusRtu;
	f->setDirUp();
	return f;
}

CFrameModbusRtu* CModbusRtuMaster::genTxTempFrame(){
	log().debug(THISMODULE "设置下行报文");
	CFrameModbusRtu* f = new CFrameModbusRtu;
	f->setDirDn();
	return f;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskStart_call( const ts_t& ts,const rts_t& rts ){
	CModbusRtuMaster::EAction act =  taskStart_call(txFrame(),ts,rts);
	if( act==Action_Send || act==Action_SendAndReTime )
		wait(rts);

	return act;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskDo_call( const ts_t& ts,const rts_t& rts ){
	CModbusRtuMaster::EAction act =  taskDo_call( txFrame(),ts,rts );
	if( act==Action_Send || act==Action_SendAndReTime )
		wait( rts );

	return act;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskStart_syncClock( const ts_t& ts,const rts_t& rts ){
	CModbusRtuMaster::EAction act =  taskStart_syncClock( txFrame(),ts,rts );
	if( act==Action_Send || act==Action_SendAndReTime )
		wait( rts );

	return act;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskDo_syncClock( const ts_t& ts,const rts_t& rts ){
	CModbusRtuMaster::EAction act =  taskDo_syncClock( txFrame(),ts,rts );
	if( act==Action_Send || act==Action_SendAndReTime )
		wait( rts );

	return act;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskStart_remoteControl( const ts_t& ts,const rts_t& rts ){
	CModbusRtuMaster::EAction act = taskStart_remoteControl( txFrame(),ts,rts );
	if( act==Action_Send || act==Action_SendAndReTime )
		wait( rts );

	return act;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskDo_remoteControl( const ts_t& ts,const rts_t& rts ){
	CModbusRtuMaster::EAction act =  taskDo_remoteControl( txFrame(),ts,rts );
	if( act==Action_Send || act==Action_SendAndReTime )
		wait( rts );

	return act;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskStart_parameters( const ts_t& ts,const rts_t& rts ){
	CModbusRtuMaster::EAction act =  taskStart_parameters( txFrame(),ts,rts );
	if( act==Action_Send || act==Action_SendAndReTime )
		wait( rts );

	return act;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskDo_parameters( const ts_t& ts,const rts_t& rts ){
	CModbusRtuMaster::EAction act =  taskDo_parameters( txFrame(),ts,rts );
	if( act==Action_Send || act==Action_SendAndReTime )
		wait( rts );

	return act;
}

///////////////////////////////////////

CModbusRtuMaster::EAction CModbusRtuMaster::taskStart_call( CFrameModbusRtu&,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "默认无操作");
	m_taskCall = Started;
	return Action_Nothing;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskDo_call( CFrameModbusRtu&,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "默认无操作");
	m_taskCall = Success;
	return Action_Nothing;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskStart_syncClock( CFrameModbusRtu& ,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "默认无操作");
	m_taskClock = Started;
	return Action_Nothing;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskDo_syncClock( CFrameModbusRtu& ,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "默认无操作");
	m_taskClock = Success;
	return Action_Nothing;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskStart_remoteControl( CFrameModbusRtu& ,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "默认无操作");
	m_taskRmtCtl = Started;
	return Action_Nothing;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskDo_remoteControl( CFrameModbusRtu& ,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "默认无操作");
	m_taskRmtCtl = Success;
	return Action_Nothing;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskStart_parameters( CFrameModbusRtu& ,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "默认无操作");
	m_taskParas = Started;
	return Action_Nothing;
}

CModbusRtuMaster::EAction CModbusRtuMaster::taskDo_parameters( CFrameModbusRtu& ,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "默认无操作");
	m_taskParas = Success;
	return Action_Nothing;
}

//========================
CModbusRtuMaster::EAction CModbusRtuMaster::dealRxResponse_readCoils( const CFrameModbusRtu& rf,CFrameModbusRtu& tf,const ts_t& ts,const rts_t& rts ){
	dm::uint16 startAddr = tf.getDataAsUint16(0,0);
	dm::uint16 quantity = tf.getDataAsUint16(0,1);

	if( rf.isUpError() ){
		log().debug(THISMODULE "收到错误帧");
		for( dm::uint16 i=0;i<quantity;++i )
			coils_01_error( startAddr+i,(CFrameModbusRtu::EErrCode)*(rf.getData()),ts,rts );
	}else{
		if( rf.getData()[0]!=CFrameModbusRtu::getDataLenByBits(quantity) ){
			log().warnning(THISMODULE "收到数据个数不匹配");
			return Action_Nothing;
		}

		log().debug(THISMODULE "处理数据");
		for( dm::uint16 i=0;i<quantity;++i )
			coils_01( startAddr+i,rf.getDataAsBit(1,i),ts,rts );
	}

	log().debug(THISMODULE "继续处理");
	return timedRefresh(ts,rts);
}

CModbusRtuMaster::EAction CModbusRtuMaster::dealRxResponse_readDiscreteInputs( const CFrameModbusRtu& rf,CFrameModbusRtu& tf,const ts_t& ts,const rts_t& rts ){
	dm::uint16 startAddr = tf.getDataAsUint16(0,0);
	dm::uint16 quantity = tf.getDataAsUint16(0,1);
	if( rf.isUpError() ){
		log().debug(THISMODULE "收到错误帧");
		for( dm::uint16 i=0;i<quantity;++i )
			discreteInputs_02_error( startAddr+i,(CFrameModbusRtu::EErrCode)*(rf.getData()),ts,rts );
	}else{
		if( rf.getData()[0]!=CFrameModbusRtu::getDataLenByBits(quantity) )
			return Action_Nothing;
		for( dm::uint16 i=0;i<quantity;++i )
			discreteInputs_02( startAddr+i,rf.getDataAsBit(1,i),ts,rts );
	}

	log().debug(THISMODULE "继续处理");
	return timedRefresh(ts,rts);
}

CModbusRtuMaster::EAction CModbusRtuMaster::dealRxResponse_readHoldingRegisters( const CFrameModbusRtu& rf,CFrameModbusRtu& tf,const ts_t& ts,const rts_t& rts ){
	dm::uint16 startAddr = tf.getDataAsUint16(0,0);
	dm::uint16 quantity = tf.getDataAsUint16(0,1);
	if( rf.isUpError() ){
		log().debug(THISMODULE "收到错误帧");
		for( dm::uint16 i=0;i<quantity;++i )
			holdingRegisters_03_error( startAddr+i,(CFrameModbusRtu::EErrCode)*(rf.getData()),ts,rts );
	}else{
		if( rf.getData()[0]!=(quantity*2) ){
			log().debug(THISMODULE "收到读寄存器返回 成功,但是数量不对");
			return Action_Nothing;
		}
		log().debug(THISMODULE "收到读寄存器返回 成功");
		for( dm::uint16 i=0;i<quantity;++i )
			holdingRegisters_03( startAddr+i,rf.getDataAsUint16(1,i),ts,rts );
	}

	log().debug(THISMODULE "继续处理");
	return timedRefresh(ts,rts);
}

CModbusRtuMaster::EAction CModbusRtuMaster::dealRxResponse_readInputRegisters( const CFrameModbusRtu& rf,CFrameModbusRtu& tf,const ts_t& ts,const rts_t& rts ){
	dm::uint16 startAddr = tf.getDataAsUint16(0,0);
	dm::uint16 quantity = tf.getDataAsUint16(0,1);
	if( rf.isUpError() ){
		log().debug(THISMODULE "收到错误帧");
		for( dm::uint16 i=0;i<quantity;++i )
			inputRegisters_04_error( startAddr+i,(CFrameModbusRtu::EErrCode)*(rf.getData()),ts,rts );
	}else{
		if( rf.getData()[0]!=(quantity*2) )
			return Action_Nothing;
		for( dm::uint16 i=0;i<quantity;++i )
			inputRegisters_04( startAddr+i,rf.getDataAsUint16(1,i),ts,rts );
	}

	log().debug(THISMODULE "继续处理");
	return timedRefresh(ts,rts);
}

CModbusRtuMaster::EAction CModbusRtuMaster::dealRxResponse_writeSingleCoil( const CFrameModbusRtu&,CFrameModbusRtu&,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "无操作");
	return Action_Nothing;
}

CModbusRtuMaster::EAction CModbusRtuMaster::dealRxResponse_writeSingleRegister( const CFrameModbusRtu& rf,CFrameModbusRtu&,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	if( rf.isUpError() ){
		log().debug(THISMODULE "收到错误帧");
	}else{
		log().debug(THISMODULE "写寄存器返回 成功");
	}

	log().debug(THISMODULE "无操作");
	return Action_Nothing;
}

CModbusRtuMaster::EAction CModbusRtuMaster::dealRxResponse_writeMultipleCoils( const CFrameModbusRtu&,CFrameModbusRtu&,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "无操作");
	return Action_Nothing;
}

CModbusRtuMaster::EAction CModbusRtuMaster::dealRxResponse_writeMultipleRegisters( const CFrameModbusRtu&,CFrameModbusRtu&,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "无操作");
	return Action_Nothing;
}

void CModbusRtuMaster::coils_01_error( const dm::uint16&,const CFrameModbusRtu::EErrCode&,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "无操作");
}

void CModbusRtuMaster::coils_01( const dm::uint16&,const dm::uint8&,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "无操作");
}

void CModbusRtuMaster::discreteInputs_02_error( const dm::uint16&,const CFrameModbusRtu::EErrCode&,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "无操作");
}

void CModbusRtuMaster::discreteInputs_02( const dm::uint16&,const dm::uint8&,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "无操作");
}

void CModbusRtuMaster::holdingRegisters_03_error( const dm::uint16&,const CFrameModbusRtu::EErrCode&,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "无操作");
}

void CModbusRtuMaster::holdingRegisters_03( const dm::uint16&,const dm::uint16&,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "默认无操作");
}

void CModbusRtuMaster::inputRegisters_04_error( const dm::uint16&,const CFrameModbusRtu::EErrCode&,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "无操作");
}

void CModbusRtuMaster::inputRegisters_04( const dm::uint16&,const dm::uint16&,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	log().debug(THISMODULE "无操作");
}

}
}
